在Go Language Specification中,它提到了标签的简要概述:
字段声明后面可以跟一个可选的字符串文字标记,它成为相应字段声明中所有字段的属性。标签通过反射界面可见,但在其他方面被忽略。 golang // A struct corresponding to the TimeStamp protocol buffer. // The tag strings define the protocol buffer field numbers. struct { microsec uint64 "field 1" serverIP6 uint64 "field 2" process string "field 3" }
字段声明后面可以跟一个可选的字符串文字标记,它成为相应字段声明中所有字段的属性。标签通过反射界面可见,但在其他方面被忽略。
golang // A struct corresponding to the TimeStamp protocol buffer. // The tag strings define the protocol buffer field numbers. struct { microsec uint64 "field 1" serverIP6 uint64 "field 2" process string "field 3" }
这是一个非常简短的解释 IMO,我想知道是否有人可以向我提供这些标签的用途?
字段的标签允许您将元信息附加到可以使用反射获取的字段。通常它用于提供有关如何将结构字段编码为另一种格式或从另一种格式解码(或从数据库中存储/检索)的转换信息,但您可以使用它来存储您想要的任何元信息,或者用于另一个包装或供您自己使用。
正如 的文档中所提到的reflect.StructTag,按照惯例,标记字符串的值是一个以空格分隔的key:"value"对列表,例如:
reflect.StructTag
key:"value"
type User struct { Name string `json:"name" xml:"name"` }
key通常表示后续用于的包,例如"value"密钥json由encoding/json包处理/使用。
key
"value"
json
encoding/json
如果要在 中传递多个信息"value",通常用逗号 ( ',') 分隔来指定,例如
','
Name string `json:"name,omitempty" xml:"name"`
通常一个短划线值 ( '-')"value"表示从进程中排除该字段的方式(例如,如果json它意味着不编组或解组该字段)。
'-'
我们可以使用反射(reflect包)来访问结构字段的标记值。基本上我们需要获取Type我们的结构体,然后我们可以查询字段,例如使用Type.Field(i int)or Type.FieldByName(name string)。这些方法返回一个StructField描述/表示结构字段的值;并且StructField.Tag是类型[ StructTag] 6的值,它描述/表示标签值。
reflect
Type
Type.Field(i int)
Type.FieldByName(name string)
StructField
StructField.Tag
StructTag
之前我们谈到了“约定”。这个约定意味着如果您遵循它,您可以使用StructTag.Get(key string)解析标签值并返回您指定的值的"value"方法key。该约定已实现/内置到此Get()方法中。如果您不遵守约定,Get()将无法解析key:"value"对并找到您要查找的内容。这也不是问题,但是您需要实现自己的解析逻辑。
StructTag.Get(key string)
Get()
还有一个StructTag.Lookup()(在 Go 1.7 中添加)“类似Get()但将不包含给定键的标签与将空字符串与给定键相关联的标签区分开来”。
StructTag.Lookup()
所以让我们看一个简单的例子:
type User struct { Name string `mytag:"MyName"` Email string `mytag:"MyEmail"` } u := User{"Bob", "bob@mycompany.com"} t := reflect.TypeOf(u) for _, fieldName := range []string{"Name", "Email"} { field, found := t.FieldByName(fieldName) if !found { continue } fmt.Printf("\nField: User.%s\n", fieldName) fmt.Printf("\tWhole tag value : %q\n", field.Tag) fmt.Printf("\tValue of 'mytag': %q\n", field.Tag.Get("mytag")) }
输出(在Go Playground上试试):
Field: User.Name Whole tag value : "mytag:\"MyName\"" Value of 'mytag': "MyName" Field: User.Email Whole tag value : "mytag:\"MyEmail\"" Value of 'mytag': "MyEmail"
GopherCon 2015 有一个关于结构标签的演示文稿,称为:
结构标签的多面性(幻灯片)(和视频)
json.Marshal()
xml
encoding/xml
xml.Marshal()
bson
bson.Marshal()
protobuf
github.com/golang/protobuf/proto
yaml
gopkg.in/yaml.v2
yaml.Marshal()
db
github.com/jmoiron/sqlx
github.com/go-gorp/gorp
orm
github.com/astaxie/beego/orm
gorm
gorm.io/gorm
valid
github.com/asaskevich/govalidator
datastore
appengine/datastore
schema
github.com/gorilla/schema
struct
asn
encoding/asn1
asn1.Marshal()
asn1.Unmarshal()
csv
github.com/gocarina/gocsv
env
github.com/caarlos0/env